1 Preparations for analysis

Loading packages to simulate and manipulate data. You need to have the pacman package installed. If you do not have it, try this install.packages("pacman").

pacman::p_load(tidyverse, MASS, psych, lavaan)
pacman::p_load_gh("tidyverse/multidplyr")

2 Simulate data

Data generation is performed by simulating multivariate data based on the following conditions: - Correlation matrix between the items: 0.10, 0.15, 0.20, 0.25 - Number of observations: 50, 100, 250, 500, 1000 - Number of items: 3 to 12 items - Number of replications: 1000

In this way, 200 dataframes are generated with different amounts of data within each of them, which will have 1,000 replications. In total, 200,000 dataframes with observations within each of them will be taken for analysis.

2.1 Generate matrices and observations

Create the variables that indicate the conditions

set.seed(2019)

r <- seq(0.10, 0.25, 0.05) ## Correlations from 0.10 to 0.25
n <- c(50, 100, 250, 500, 1000) ## Size samples
replic <- 1000

There will be a quadruple for loop to generate the data 10x5x4x1000(rep). This code is computationally intensive and consumes approximately 4.8 gb of ram.

# Create blank lists
sigma <- list() # It will store the matrices of the items
items <- list() # It will store the generated items 

for(i in 1:10) { # 10 different quantity of items 
  sigma[[i]] <- list() 
  items[[i]] <- list() 
  for (j in seq_along(r)) { # Change according to the different correlation matrices
    sigma[[i]][[j]] <- matrix(data = rep(c(1, rep(r[j], i+2)), i+2),
                              nrow = i+2, 
                              ncol = i+2) 
    items[[i]][[j]] <- list()
    for (k in seq_along(n)) { # Change based on sample size 
      items[[i]][[j]][[k]] <- list()
      for(l in 1:replic) { # Change based on number of replications (1,000)
        items[[i]][[j]][[k]][[l]] <- mvrnorm(n = n[k], 
                                             mu = rep(0, i+2), 
                                             Sigma = sigma[[i]][[j]]) %>% 
          as_tibble() %>% 
            mutate_all(list(Item = ~ findInterval(., c(-Inf, -2,  -1, 1,  2, Inf)))) # Perform a symmetrical scaling of the items
      }
    }
  }
}
The `x` argument of `as_tibble.matrix()` must have column names if `.name_repair` is omitted as of tibble 2.0.0.
Using compatibility `.name_repair`.
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.
# Delete temporary indexes
rm(i, j, k, l)

2.2 Format the data as dataframe / tibbles

The nested lists that we have created will be put together in order to have them identified with columns that indicate the sample size, the correlation and the replication number with which they were simulated.

temp <- items
items <- list()
for(i in 1:10) {
  items[[i]] <- list()
  for(j in seq_along(r)) {
    items[[i]][[j]] <- list()
    for(k in seq_along(n)) {
      items[[i]][[j]][[k]] <- temp[[i]][[j]][[k]] %>% 
        bind_rows(.id = "replic")
    }
    items[[i]][[j]] <- items[[i]][[j]] %>% 
      bind_rows(.id = "n") %>% 
      mutate(n = recode(n, "1" = 50, "2" = 100,
                        "3" = 250, "4" = 500, 
                        "5" = 1000))
  }
  items[[i]] <- items[[i]] %>% 
    bind_rows(.id = "correlation") %>% 
    mutate(correlation = recode(correlation, "1" = 0.1,
                                "2" = 0.15, "3" = 0.2,
                                "4" = 0.25)) %>% 
  group_nest(correlation, n, replic)
}
items <- items %>% 
  bind_rows(.id = "items") %>% 
  mutate(items = recode(items, "1" = "3 items",
                        "2" = "4 items", "3" = "5 items",
                        "4" = "6 items", "5" = "7 items",
                        "6" = "8 items", "7" = "9 items",
                        "8" = "10 items", "9" = "11 items",
                        "10" = "12 items"))

items

3 Reliability analysis

The multidplyr package will be used so that the calculation uses all the processor cores.

cluster <- new_cluster(parallel::detectCores())

items <- items %>% 
  partition(cluster) %>% 
  mutate(
    alfa_psych = purrr::map(data,
                            ~ psych::alpha(dplyr::select(., -dplyr::ends_with("Item")))),
    alfa_coef  = purrr::map_dbl(alfa_psych,
                                ~ purrr::pluck(.x, "total", "raw_alpha"))
  ) %>% 
  collect()

items

To lighten the consumption of ram memory, another object is created where it contains the variables of interest and deletes others (such as data).

item_fiab <- items %>% 
  dplyr::select(-c(data, alfa_psych)) %>% 
  mutate(
    replic = as.numeric(replic),
    items = fct_relevel(items, "12 items", "11 items", "10 items", after = Inf)
  ) %>% 
  arrange(items, correlation, n, replic)

item_fiab
# Delete `items` object
rm(items)
gc()

4 Make summary graph

The alpha coefficients that are greater than 0.7 are counted to analyze their frequency according to the simulation conditions.

item_fiab <- item_fiab %>% 
  mutate(
    dx_alfa_coef = case_when(
      alfa_coef >= 0.7 ~ "good",
      TRUE ~ "bad"
      )
  ) %>% 
  rename(n_samp = n)

item_fiab

Data is sorted

item_plot <- item_fiab %>% 
  group_by(items, n_samp, correlation) %>% 
  count(dx_alfa_coef) %>% 
  ungroup() %>% 
  pivot_wider(
    names_from = dx_alfa_coef,
    values_from = n,
    values_fill = list(n = 0)
  ) %>% 
  mutate(
    Percentage = good/(bad + good)
  ) 

item_plot

From this ordering of the data a bar graph is made with ggplot2

plot_item <- item_plot %>% 
  ggplot(aes(x = correlation, 
             y = Percentage, 
             alpha = correlation, 
             label = scales::percent(Percentage,
                                     accuracy = 1)))  +
  geom_col() +
  scale_y_continuous(
    limits = c(-0.1, 1.2),
    breaks = c(0, 0.5, 1),
    labels = scales::percent_format()
    ) +
  coord_flip() +
  geom_label(
    size = 2.2,
    label.size = 0.25, 
    label.r = unit(0.10, "lines"),
    label.padding = unit(0.15, "lines"),
    show.legend = FALSE
    ) +
  scale_alpha_continuous(
    name = "Correlation",
    guide = guide_legend(reverse = TRUE)
    ) +
  facet_grid(n_samp ~ items) +
  labs(
    title = "Percentage of cases with alpha reliability greater than 0.70",
    subtitle = "The percentage is calculated based on 1000 replications in each condition",
    y = "",
    x = ""
  ) + 
  theme_bw() +
  theme(
    plot.title = element_text(hjust = 0.5),
    plot.subtitle = element_text(hjust = 0.5),
    text = element_text(
      size = 11,
      face="bold"), 
    axis.text = element_text(
      size = 7,
      face="plain",
      colour="black"),
    legend.title = element_text(
      size = 11,
      face = "bold"
    ),
    legend.text = element_text(
      face="plain",
      colour="black",
      size=10)
  )

5 Information about session Rstudio

sessionInfo()
R version 4.0.0 (2020-04-24)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Pop!_OS 20.04 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0

locale:
 [1] LC_CTYPE=es_ES.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=es_PE.UTF-8        LC_COLLATE=es_ES.UTF-8    
 [5] LC_MONETARY=es_PE.UTF-8    LC_MESSAGES=es_ES.UTF-8   
 [7] LC_PAPER=es_PE.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=es_PE.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] multidplyr_0.0.0.9000 lavaan_0.6-6          psych_1.9.12.31      
 [4] MASS_7.3-51.6         forcats_0.5.0         stringr_1.4.0        
 [7] dplyr_0.8.99.9003     purrr_0.3.4           readr_1.3.1          
[10] tidyr_1.0.3           tibble_3.0.1          ggplot2_3.3.0        
[13] tidyverse_1.3.0      

loaded via a namespace (and not attached):
 [1] httr_1.4.1         jsonlite_1.6.1     modelr_0.1.8       StanHeaders_2.19.2
 [5] assertthat_0.2.1   stats4_4.0.0       cellranger_1.1.0   pbivnorm_0.6.0    
 [9] pillar_1.4.4       backports_1.1.7    lattice_0.20-41    glue_1.4.1        
[13] digest_0.6.25      rvest_0.3.5        colorspace_1.4-1   htmltools_0.4.0   
[17] pkgconfig_2.0.3    rstan_2.19.3       broom_0.5.6        haven_2.2.0       
[21] scales_1.1.1       processx_3.4.2     generics_0.0.2     farver_2.0.3      
[25] ellipsis_0.3.1     pacman_0.5.1       withr_2.2.0        cli_2.0.2         
[29] mnormt_1.5-7       magrittr_1.5       crayon_1.3.4       readxl_1.3.1      
[33] evaluate_0.14      ps_1.3.3           fs_1.4.1           fansi_0.4.1       
[37] nlme_3.1-147       xml2_1.3.2         pkgbuild_1.0.8     tools_4.0.0       
[41] loo_2.2.0          prettyunits_1.1.1  hms_0.5.3          lifecycle_0.2.0   
[45] matrixStats_0.56.0 munsell_0.5.0      reprex_0.3.0       callr_3.4.3       
[49] packrat_0.5.0      compiler_4.0.0     rlang_0.4.6.9000   grid_4.0.0        
[53] rstudioapi_0.11    labeling_0.3       rmarkdown_2.1      gtable_0.3.0      
[57] inline_0.3.15      DBI_1.1.0          R6_2.4.1           gridExtra_2.3     
[61] lubridate_1.7.8    knitr_1.28         utf8_1.1.4         stringi_1.4.6     
[65] parallel_4.0.0     Rcpp_1.0.4.6       vctrs_0.3.0.9000   dbplyr_1.4.3      
[69] tidyselect_1.1.0   xfun_0.13         
LS0tCnRpdGxlOiAiVGhlIHdvcmxkIHJldm9sdmVzIGFyb3VuZCBDcm9uYmFjaOKAmXMgYWxwaGEgKM6xIOKJpSAwLjcwKSIKZGF0ZTogIjE5LzUvMjAyMCIKYXV0aG9yOgogIC0gbmFtZTogSm9zw6kgVmVudHVyYS1MZcOzbgogICAgZW1haWw6IGpvc2UudmVudHVyYUB1cG4ucGUKICAgIGFmZmlsaWF0aW9uOiBVbml2ZXJzaWRhZCBQcml2YWRhIGRlbCBOb3J0ZQogIC0gbmFtZTogQnJpYW4gTi4gUGXDsWEtQ2FsZXJvCiAgICBlbWFpbDogYnJpYW5tc21AZ21haWwuY29tCiAgICBhZmZpbGlhdGlvbjogR3J1cG8gZGUgRXN0dWRpb3MgQXZhbmNlcyBlbiBNZWRpY2nDs24gUHNpY29sw7NnaWNhLCBVbml2ZXJzaWRhZCBOYWNpb25hbCBNYXlvciBkZSBTYW4gTWFyY29zLCBMaW1hLCBQZXLDugpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRvYzogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCiMgUHJlcGFyYXRpb25zIGZvciBhbmFseXNpcwoKTG9hZGluZyBwYWNrYWdlcyB0byBzaW11bGF0ZSBhbmQgbWFuaXB1bGF0ZSBkYXRhLiBZb3UgbmVlZCB0byBoYXZlIHRoZSBgcGFjbWFuYCBwYWNrYWdlIGluc3RhbGxlZC4gSWYgeW91IGRvIG5vdCBoYXZlIGl0LCB0cnkgdGhpcyBgaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIilgLgpgYGB7cn0KcGFjbWFuOjpwX2xvYWQodGlkeXZlcnNlLCBNQVNTLCBwc3ljaCwgbGF2YWFuKQpwYWNtYW46OnBfbG9hZF9naCgidGlkeXZlcnNlL211bHRpZHBseXIiKQpgYGAKCiMgU2ltdWxhdGUgZGF0YQoKRGF0YSBnZW5lcmF0aW9uIGlzIHBlcmZvcm1lZCBieSBzaW11bGF0aW5nIG11bHRpdmFyaWF0ZSBkYXRhIGJhc2VkIG9uIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKLSBDb3JyZWxhdGlvbiBtYXRyaXggYmV0d2VlbiB0aGUgaXRlbXM6IDAuMTAsIDAuMTUsIDAuMjAsIDAuMjUKLSBOdW1iZXIgb2Ygb2JzZXJ2YXRpb25zOiA1MCwgMTAwLCAyNTAsIDUwMCwgMTAwMAotIE51bWJlciBvZiBpdGVtczogMyB0byAxMiBpdGVtcwotIE51bWJlciBvZiByZXBsaWNhdGlvbnM6IDEwMDAKCkluIHRoaXMgd2F5LCAyMDAgKmRhdGFmcmFtZXMqIGFyZSBnZW5lcmF0ZWQgd2l0aCBkaWZmZXJlbnQgYW1vdW50cyBvZiBkYXRhIHdpdGhpbiBlYWNoIG9mIHRoZW0sIHdoaWNoIHdpbGwgaGF2ZSAxLDAwMCAqcmVwbGljYXRpb25zKi4gSW4gdG90YWwsIDIwMCwwMDAgKmRhdGFmcmFtZXMqIHdpdGggb2JzZXJ2YXRpb25zIHdpdGhpbiBlYWNoIG9mIHRoZW0gd2lsbCBiZSB0YWtlbiBmb3IgYW5hbHlzaXMuCgojIyBHZW5lcmF0ZSBtYXRyaWNlcyBhbmQgb2JzZXJ2YXRpb25zCgpDcmVhdGUgdGhlIHZhcmlhYmxlcyB0aGF0IGluZGljYXRlIHRoZSBjb25kaXRpb25zCgpgYGB7cn0Kc2V0LnNlZWQoMjAxOSkKCnIgPC0gc2VxKDAuMTAsIDAuMjUsIDAuMDUpICMjIENvcnJlbGF0aW9ucyBmcm9tIDAuMTAgdG8gMC4yNQpuIDwtIGMoNTAsIDEwMCwgMjUwLCA1MDAsIDEwMDApICMjIFNpemUgc2FtcGxlcwpyZXBsaWMgPC0gMTAwMApgYGAKClRoZXJlIHdpbGwgYmUgYSBxdWFkcnVwbGUgZm9yIGxvb3AgdG8gZ2VuZXJhdGUgdGhlIGRhdGEgMTB4NXg0eDEwMDAocmVwKS4KKlRoaXMgY29kZSBpcyBjb21wdXRhdGlvbmFsbHkgaW50ZW5zaXZlIGFuZCBjb25zdW1lcyBhcHByb3hpbWF0ZWx5IDQuOCBnYiBvZiByYW0uKgoKYGBge3J9CiMgQ3JlYXRlIGJsYW5rIGxpc3RzCnNpZ21hIDwtIGxpc3QoKSAjIEl0IHdpbGwgc3RvcmUgdGhlIG1hdHJpY2VzIG9mIHRoZSBpdGVtcwppdGVtcyA8LSBsaXN0KCkgIyBJdCB3aWxsIHN0b3JlIHRoZSBnZW5lcmF0ZWQgaXRlbXMgCgpmb3IoaSBpbiAxOjEwKSB7ICMgMTAgZGlmZmVyZW50IHF1YW50aXR5IG9mIGl0ZW1zIAogIHNpZ21hW1tpXV0gPC0gbGlzdCgpIAogIGl0ZW1zW1tpXV0gPC0gbGlzdCgpIAogIGZvciAoaiBpbiBzZXFfYWxvbmcocikpIHsgIyBDaGFuZ2UgYWNjb3JkaW5nIHRvIHRoZSBkaWZmZXJlbnQgY29ycmVsYXRpb24gbWF0cmljZXMKICAgIHNpZ21hW1tpXV1bW2pdXSA8LSBtYXRyaXgoZGF0YSA9IHJlcChjKDEsIHJlcChyW2pdLCBpKzIpKSwgaSsyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnJvdyA9IGkrMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSBpKzIpIAogICAgaXRlbXNbW2ldXVtbal1dIDwtIGxpc3QoKQogICAgZm9yIChrIGluIHNlcV9hbG9uZyhuKSkgeyAjIENoYW5nZSBiYXNlZCBvbiBzYW1wbGUgc2l6ZSAKICAgICAgaXRlbXNbW2ldXVtbal1dW1trXV0gPC0gbGlzdCgpCiAgICAgIGZvcihsIGluIDE6cmVwbGljKSB7ICMgQ2hhbmdlIGJhc2VkIG9uIG51bWJlciBvZiByZXBsaWNhdGlvbnMgKDEsMDAwKQogICAgICAgIGl0ZW1zW1tpXV1bW2pdXVtba11dW1tsXV0gPC0gbXZybm9ybShuID0gbltrXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11ID0gcmVwKDAsIGkrMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaWdtYSA9IHNpZ21hW1tpXV1bW2pdXSkgJT4lIAogICAgICAgICAgYXNfdGliYmxlKCkgJT4lIAogICAgICAgICAgICBtdXRhdGVfYWxsKGxpc3QoSXRlbSA9IH4gZmluZEludGVydmFsKC4sIGMoLUluZiwgLTIsICAtMSwgMSwgIDIsIEluZikpKSkgIyBQZXJmb3JtIGEgc3ltbWV0cmljYWwgc2NhbGluZyBvZiB0aGUgaXRlbXMKICAgICAgfQogICAgfQogIH0KfQoKIyBEZWxldGUgdGVtcG9yYXJ5IGluZGV4ZXMKcm0oaSwgaiwgaywgbCkKYGBgCgojIyBGb3JtYXQgdGhlIGRhdGEgYXMgZGF0YWZyYW1lIC8gdGliYmxlcwoKVGhlIG5lc3RlZCBsaXN0cyB0aGF0IHdlIGhhdmUgY3JlYXRlZCB3aWxsIGJlIHB1dCB0b2dldGhlciBpbiBvcmRlciB0byBoYXZlIHRoZW0gaWRlbnRpZmllZCB3aXRoIGNvbHVtbnMgdGhhdCBpbmRpY2F0ZSB0aGUgc2FtcGxlIHNpemUsIHRoZSBjb3JyZWxhdGlvbiBhbmQgdGhlIHJlcGxpY2F0aW9uIG51bWJlciB3aXRoIHdoaWNoIHRoZXkgd2VyZSBzaW11bGF0ZWQuCgpgYGB7cn0KdGVtcCA8LSBpdGVtcwppdGVtcyA8LSBsaXN0KCkKZm9yKGkgaW4gMToxMCkgewogIGl0ZW1zW1tpXV0gPC0gbGlzdCgpCiAgZm9yKGogaW4gc2VxX2Fsb25nKHIpKSB7CiAgICBpdGVtc1tbaV1dW1tqXV0gPC0gbGlzdCgpCiAgICBmb3IoayBpbiBzZXFfYWxvbmcobikpIHsKICAgICAgaXRlbXNbW2ldXVtbal1dW1trXV0gPC0gdGVtcFtbaV1dW1tqXV1bW2tdXSAlPiUgCiAgICAgICAgYmluZF9yb3dzKC5pZCA9ICJyZXBsaWMiKQogICAgfQogICAgaXRlbXNbW2ldXVtbal1dIDwtIGl0ZW1zW1tpXV1bW2pdXSAlPiUgCiAgICAgIGJpbmRfcm93cyguaWQgPSAibiIpICU+JSAKICAgICAgbXV0YXRlKG4gPSByZWNvZGUobiwgIjEiID0gNTAsICIyIiA9IDEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgIjMiID0gMjUwLCAiNCIgPSA1MDAsIAogICAgICAgICAgICAgICAgICAgICAgICAiNSIgPSAxMDAwKSkKICB9CiAgaXRlbXNbW2ldXSA8LSBpdGVtc1tbaV1dICU+JSAKICAgIGJpbmRfcm93cyguaWQgPSAiY29ycmVsYXRpb24iKSAlPiUgCiAgICBtdXRhdGUoY29ycmVsYXRpb24gPSByZWNvZGUoY29ycmVsYXRpb24sICIxIiA9IDAuMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMiIgPSAwLjE1LCAiMyIgPSAwLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjQiID0gMC4yNSkpICU+JSAKICBncm91cF9uZXN0KGNvcnJlbGF0aW9uLCBuLCByZXBsaWMpCn0KYGBgCgpgYGB7ciBlY2hvID0gVFJVRSwgcmVzdWx0cyA9ICdoaWRlJ30KIyBEZWxldGUgdGVtcG9yYXJ5IGluZGV4ZXMKcm0oaSwgaiwgaywgdGVtcCkKZ2MoKQpgYGAKCmBgYHtyfQppdGVtcyA8LSBpdGVtcyAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJpdGVtcyIpICU+JSAKICBtdXRhdGUoaXRlbXMgPSByZWNvZGUoaXRlbXMsICIxIiA9ICIzIGl0ZW1zIiwKICAgICAgICAgICAgICAgICAgICAgICAgIjIiID0gIjQgaXRlbXMiLCAiMyIgPSAiNSBpdGVtcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICI0IiA9ICI2IGl0ZW1zIiwgIjUiID0gIjcgaXRlbXMiLAogICAgICAgICAgICAgICAgICAgICAgICAiNiIgPSAiOCBpdGVtcyIsICI3IiA9ICI5IGl0ZW1zIiwKICAgICAgICAgICAgICAgICAgICAgICAgIjgiID0gIjEwIGl0ZW1zIiwgIjkiID0gIjExIGl0ZW1zIiwKICAgICAgICAgICAgICAgICAgICAgICAgIjEwIiA9ICIxMiBpdGVtcyIpKQoKaXRlbXMKYGBgCgoKIyBSZWxpYWJpbGl0eSBhbmFseXNpcwoKVGhlIGBtdWx0aWRwbHlyYCBwYWNrYWdlIHdpbGwgYmUgdXNlZCBzbyB0aGF0IHRoZSBjYWxjdWxhdGlvbiB1c2VzIGFsbCB0aGUgcHJvY2Vzc29yIGNvcmVzLgoKYGBge3J9CmNsdXN0ZXIgPC0gbmV3X2NsdXN0ZXIocGFyYWxsZWw6OmRldGVjdENvcmVzKCkpCgppdGVtcyA8LSBpdGVtcyAlPiUgCiAgcGFydGl0aW9uKGNsdXN0ZXIpICU+JSAKICBtdXRhdGUoCiAgICBhbGZhX3BzeWNoID0gcHVycnI6Om1hcChkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfiBwc3ljaDo6YWxwaGEoZHBseXI6OnNlbGVjdCguLCAtZHBseXI6OmVuZHNfd2l0aCgiSXRlbSIpKSkpLAogICAgYWxmYV9jb2VmICA9IHB1cnJyOjptYXBfZGJsKGFsZmFfcHN5Y2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfiBwdXJycjo6cGx1Y2soLngsICJ0b3RhbCIsICJyYXdfYWxwaGEiKSkKICApICU+JSAKICBjb2xsZWN0KCkKCml0ZW1zCmBgYAoKVG8gbGlnaHRlbiB0aGUgY29uc3VtcHRpb24gb2YgcmFtIG1lbW9yeSwgYW5vdGhlciBvYmplY3QgaXMgY3JlYXRlZCB3aGVyZSBpdCBjb250YWlucyB0aGUgdmFyaWFibGVzIG9mIGludGVyZXN0IGFuZCBkZWxldGVzIG90aGVycyAoc3VjaCBhcyBgZGF0YWApLgoKYGBge3J9Cml0ZW1fZmlhYiA8LSBpdGVtcyAlPiUgCiAgZHBseXI6OnNlbGVjdCgtYyhkYXRhLCBhbGZhX3BzeWNoKSkgJT4lIAogIG11dGF0ZSgKICAgIHJlcGxpYyA9IGFzLm51bWVyaWMocmVwbGljKSwKICAgIGl0ZW1zID0gZmN0X3JlbGV2ZWwoaXRlbXMsICIxMiBpdGVtcyIsICIxMSBpdGVtcyIsICIxMCBpdGVtcyIsIGFmdGVyID0gSW5mKQogICkgJT4lIAogIGFycmFuZ2UoaXRlbXMsIGNvcnJlbGF0aW9uLCBuLCByZXBsaWMpCgppdGVtX2ZpYWIKYGBgCgpgYGB7ciBlY2hvID0gVFJVRSwgcmVzdWx0cyA9ICdoaWRlJ30KIyBEZWxldGUgYGl0ZW1zYCBvYmplY3QKcm0oaXRlbXMpCmdjKCkKYGBgCgojIE1ha2Ugc3VtbWFyeSBncmFwaCAKClRoZSBhbHBoYSBjb2VmZmljaWVudHMgdGhhdCBhcmUgZ3JlYXRlciB0aGFuIDAuNyBhcmUgY291bnRlZCB0byBhbmFseXplIHRoZWlyIGZyZXF1ZW5jeSBhY2NvcmRpbmcgdG8gdGhlIHNpbXVsYXRpb24gY29uZGl0aW9ucy4KCmBgYHtyfQppdGVtX2ZpYWIgPC0gaXRlbV9maWFiICU+JSAKICBtdXRhdGUoCiAgICBkeF9hbGZhX2NvZWYgPSBjYXNlX3doZW4oCiAgICAgIGFsZmFfY29lZiA+PSAwLjcgfiAiZ29vZCIsCiAgICAgIFRSVUUgfiAiYmFkIgogICAgICApCiAgKSAlPiUgCiAgcmVuYW1lKG5fc2FtcCA9IG4pCgppdGVtX2ZpYWIKYGBgCgpEYXRhIGlzIHNvcnRlZApgYGB7cn0KaXRlbV9wbG90IDwtIGl0ZW1fZmlhYiAlPiUgCiAgZ3JvdXBfYnkoaXRlbXMsIG5fc2FtcCwgY29ycmVsYXRpb24pICU+JSAKICBjb3VudChkeF9hbGZhX2NvZWYpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHBpdm90X3dpZGVyKAogICAgbmFtZXNfZnJvbSA9IGR4X2FsZmFfY29lZiwKICAgIHZhbHVlc19mcm9tID0gbiwKICAgIHZhbHVlc19maWxsID0gbGlzdChuID0gMCkKICApICU+JSAKICBtdXRhdGUoCiAgICBQZXJjZW50YWdlID0gZ29vZC8oYmFkICsgZ29vZCkKICApIAoKaXRlbV9wbG90CmBgYAoKCkZyb20gdGhpcyBvcmRlcmluZyBvZiB0aGUgZGF0YSBhIGJhciBncmFwaCBpcyBtYWRlIHdpdGggYGdncGxvdDJgCgpgYGB7ciBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gOS41LCBkcGkgPSAzMDAsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQpwbG90X2l0ZW0gPC0gaXRlbV9wbG90ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb3JyZWxhdGlvbiwgCiAgICAgICAgICAgICB5ID0gUGVyY2VudGFnZSwgCiAgICAgICAgICAgICBhbHBoYSA9IGNvcnJlbGF0aW9uLCAKICAgICAgICAgICAgIGxhYmVsID0gc2NhbGVzOjpwZXJjZW50KFBlcmNlbnRhZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY2N1cmFjeSA9IDEpKSkgICsKICBnZW9tX2NvbCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICBsaW1pdHMgPSBjKC0wLjEsIDEuMiksCiAgICBicmVha3MgPSBjKDAsIDAuNSwgMSksCiAgICBsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkKICAgICkgKwogIGNvb3JkX2ZsaXAoKSArCiAgZ2VvbV9sYWJlbCgKICAgIHNpemUgPSAyLjIsCiAgICBsYWJlbC5zaXplID0gMC4yNSwgCiAgICBsYWJlbC5yID0gdW5pdCgwLjEwLCAibGluZXMiKSwKICAgIGxhYmVsLnBhZGRpbmcgPSB1bml0KDAuMTUsICJsaW5lcyIpLAogICAgc2hvdy5sZWdlbmQgPSBGQUxTRQogICAgKSArCiAgc2NhbGVfYWxwaGFfY29udGludW91cygKICAgIG5hbWUgPSAiQ29ycmVsYXRpb24iLAogICAgZ3VpZGUgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpCiAgICApICsKICBmYWNldF9ncmlkKG5fc2FtcCB+IGl0ZW1zKSArCiAgbGFicygKICAgIHRpdGxlID0gIlBlcmNlbnRhZ2Ugb2YgY2FzZXMgd2l0aCBhbHBoYSByZWxpYWJpbGl0eSBncmVhdGVyIHRoYW4gMC43MCIsCiAgICBzdWJ0aXRsZSA9ICJUaGUgcGVyY2VudGFnZSBpcyBjYWxjdWxhdGVkIGJhc2VkIG9uIDEwMDAgcmVwbGljYXRpb25zIGluIGVhY2ggY29uZGl0aW9uIiwKICAgIHkgPSAiIiwKICAgIHggPSAiIgogICkgKyAKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KAogICAgICBzaXplID0gMTEsCiAgICAgIGZhY2U9ImJvbGQiKSwgCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoCiAgICAgIHNpemUgPSA3LAogICAgICBmYWNlPSJwbGFpbiIsCiAgICAgIGNvbG91cj0iYmxhY2siKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgc2l6ZSA9IDExLAogICAgICBmYWNlID0gImJvbGQiCiAgICApLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoCiAgICAgIGZhY2U9InBsYWluIiwKICAgICAgY29sb3VyPSJibGFjayIsCiAgICAgIHNpemU9MTApCiAgKQoKYGBgCgohW10oUGxvdCBpdGVtIHN0YXR1cy5wbmcpCgojIEluZm9ybWF0aW9uIGFib3V0IHNlc3Npb24gUnN0dWRpbwpgYGB7cn0Kc2Vzc2lvbkluZm8oKQpgYGAKCg==